module fifo_port_uart(
       input        clk50M,
		 input        rst_n,
		 input [7:0]  data,
		 input        write,
		 output       wr_full,
		 output       rd_empty,
		 input        read,
		 output [7:0] q,
		 input        uart_rxd,
		 output       uart_txd
);
parameter  CLK_FREQ  = 50_000_000;
parameter  BAUD_RATE = 9600      ;
parameter  PLATFORM  = 0         ;//0:Altera 1:Xilinx 2:GoWin 3:Anlogic
localparam DIV_CNT   = 64'h100000000*BAUD_RATE*16/CLK_FREQ;
wire clken_16bps,txd_flag_w;
wire txd_en_w;
precise_divider
#(
	//DEVIDE_CNT = baud*16*2^32/freq   freq is clk50M's frequency
//	parameter		DEVIDE_CNT = 32'd351843721	//256000bps * 16
//	parameter		DEVIDE_CNT = 32'd175921860	//128000bps * 16
//	.DEVIDE_CNT(32'd158329674)                //115200bps * 16
//  .DEVIDE_CNT(32'd79164837)                 //57600bps  * 16
//	.DEVIDE_CNT(32'd13194140)	//9600bps @50Mhz
//  .DEVIDE_CNT(32'd24433592)   //9600bps @27Mhz
	.DEVIDE_CNT(DIV_CNT)
)
precise_divider_u
(
	//global clock
	.clk(clk50M),
	.rst_n(rst_n),
	
	//user interface
	//.divide_clk(),
	.divide_clken(clken_16bps)
);
wire [7:0] txfifo_q_w;
reg [7:0]  txfifo_q_r;
wire       txfifo_rd_w,txfifo_empty_w;
generate if(PLATFORM == 2) begin
//GOWIN FIFO
uart_fifo uart_txfifo(
    .Data(data), //input [7:0] Data
    .Clk(clk50M), //input Clk
    .WrEn(write), //input WrEn
    .RdEn(txfifo_rd_w), //input RdEn
    .Reset(~rst_n), //input Reset
    .Q(txfifo_q_w), //output [7:0] Q
    .Empty(txfifo_empty_w), //output Empty
    .Full(wr_full) //output Full
);
end else if(PLATFORM == 0) begin
//Altera FIFO
uart_fifo uart_txfifo (
	.aclr (~rst_n),
	.clock(clk50M),
	.data (data),
	.rdreq(txfifo_rd_w),
	.wrreq(write),
	.empty(txfifo_empty_w),
	.full (wr_full),
	.q    (txfifo_q_w)
	);
end
endgenerate
/*
uart_fifo #(
  .DEPTH( 1024 ),
  .DATA_W( 8 )
) uart_txfifo (
  .clk( clk50M ),
  .rst( ~rst_n ),
  .w_req( write ),
  .w_data( data ),
  .r_req( txfifo_rd_w ),
  .r_data( txfifo_q_w ),
  .empty( txfifo_empty_w ),
  .full( wr_full )
);
*/
assign txd_en_w = txfifo_rd_r;
uart_transfer uart_transfer_u(
	 .clk(clk50M),
	 .rst_n(rst_n),
	 .clken_16bps(clken_16bps),
	 .txd(uart_txd),		
	 .txd_en(txd_en_w),		
    .txd_data(txfifo_q_w),
	 .txd_flag(txd_flag_w)
	 );
wire rxd_flag_w;
wire [7:0] rxd_data_w;
uart_receiver uart_receiver_u(//gobal clock
	.clk(clk50M),
	.rst_n(rst_n),
	.clken_16bps(clken_16bps),
	.rxd(uart_rxd),
	.rxd_flag(rxd_flag_w),
	.rxd_data(rxd_data_w)	
	               	);
generate if(PLATFORM == 2) begin
uart_fifo uart_rxfifo(
    .Data(rxd_data_w), //input [7:0] Data
    .Clk(clk50M), //input Clk
    .WrEn(rxd_flag_w), //input WrEn
    .RdEn(read), //input RdEn
    .Reset(~rst_n), //input Reset
    .Q(q), //output [7:0] Q
    .Empty(rd_empty) //output Empty
//    .Full(wr_full) //output Full
);
end else if(PLATFORM == 0) begin
uart_fifo uart_rxfifo (
	.aclr (~rst_n),
	.clock(clk50M),
	.data (rxd_data_w),
	.rdreq(read),
	.wrreq(rxd_flag_w),
	.empty(rd_empty),
	.q    (q)
	);
end
endgenerate
/*
uart_fifo #(
  .DEPTH( 1024 ),
  .DATA_W( 8 )
) uart_rxfifo (
  .clk( clk50M ),
  .rst( ~rst_n ),
  .w_req( rxd_flag_w ),
  .w_data( rxd_data_w ),
  .r_req( read ),
  .r_data( q ),
  .empty( rd_empty )
);
*/
reg tx_state;
reg txfifo_rd_r;
assign txfifo_rd_w= (~txfifo_empty_w) & (~tx_state);
always@(posedge clk50M or negedge rst_n)
begin
if(!rst_n)
    begin
	 tx_state    <= 1'b0;
	 txfifo_rd_r <= 1'b0;
	 txfifo_q_r <= 8'd0;
	 end
else
    begin
	 txfifo_rd_r   <= txfifo_rd_w;
	 txfifo_q_r <= txfifo_rd_w?txfifo_q_w:txfifo_q_r;
	 case(tx_state)
	 1'b0:tx_state <= txfifo_empty_w?tx_state:1'b1;
	 1'b1:tx_state <= txd_flag_w?1'b0:tx_state;
	 endcase
	 end
end
endmodule 